(function(factory) {
	if (typeof define === 'function' && define.amd) {
		// AMD. Register as an anonymous module.
		define(['jquery'], factory);
	} else {
		// Browser globals
		factory(jQuery);
	}
}(function($) {
			$.timeago = function(timestamp) {
				if (timestamp instanceof Date) {
					return inWords(timestamp);
				} else if (typeof timestamp === "string") {
					return inWords($.timeago.parse(timestamp));
				} else if (typeof timestamp === "number") {
					return inWords(new Date(timestamp));
				} else {
					return inWords($.timeago.datetime(timestamp));
				}
			};
			var $t = $.timeago;
			$.extend($.timeago, {
						settings : {
							refreshMillis : 60000,
							allowFuture : false,
							localeTitle : false,
							cutoff : 0,
							strings : {
								prefixAgo : null,
								prefixFromNow : null,
								suffixAgo : "前",
								suffixFromNow : "from now",
								seconds : "1分钟",
								minute : "1分钟",
								minutes : "%d分钟",
								hour : "1小时",
								hours : "%d小时",
								day : "1天",
								days : "%d天",
								month : "1月",
								months : "%d月",
								year : "1年",
								years : "%d年",
								wordSeparator : "",
								numbers : []
							}
						},
						inWords : function(distanceMillis) {
							var $l = this.settings.strings;
							var prefix = $l.prefixAgo;
							var suffix = $l.suffixAgo;
							if (this.settings.allowFuture) {
								if (distanceMillis < 0) {
									prefix = $l.prefixFromNow;
									suffix = $l.suffixFromNow;
								}
							}
							var seconds = Math.abs(distanceMillis) / 1000;
							var minutes = seconds / 60;
							var hours = minutes / 60;
							var days = hours / 24;
							var years = days / 365;
							function substitute(stringOrFunction, number) {
								var string = $.isFunction(stringOrFunction)
										? stringOrFunction(number,
												distanceMillis)
										: stringOrFunction;
								var value = ($l.numbers && $l.numbers[number])
										|| number;
								return string.replace(/%d/i, value);
							}
							var words = seconds < 45
									&& substitute($l.seconds, Math
													.round(seconds))
									|| seconds < 90
									&& substitute($l.minute, 1)
									|| minutes < 45
									&& substitute($l.minutes, Math
													.round(minutes))
									|| minutes < 90
									&& substitute($l.hour, 1)
									|| hours < 24
									&& substitute($l.hours, Math.round(hours))
									|| hours < 42
									&& substitute($l.day, 1)
									|| days < 30
									&& substitute($l.days, Math.round(days))
									|| days < 45
									&& substitute($l.month, 1)
									|| days < 365
									&& substitute($l.months, Math.round(days
													/ 30)) || years < 1.5
									&& substitute($l.year, 1)
									|| substitute($l.years, Math.round(years));
							var separator = $l.wordSeparator || "";
							if ($l.wordSeparator === undefined) {
								separator = " ";
							}
							return $.trim([prefix, words, suffix]
									.join(separator));
						},
						parse : function(iso8601) {
							var s = $.trim(iso8601);
							s = s.replace(/\.\d+/, ""); // remove milliseconds
							s = s.replace(/-/, "/").replace(/-/, "/");
							s = s.replace(/T/, " ").replace(/Z/, " UTC");
							s = s.replace(/([\+\-]\d\d)\:?(\d\d)/, " $1$2"); // -04:00
																				// ->
																				// -0400
							return new Date(s);
						},
						datetime : function(elem) {
							var iso8601 = $t.isTime(elem) ? $(elem)
									.attr("datetime") : $(elem).attr("title");
							return $t.parse(iso8601);
						},
						isTime : function(elem) {
							// jQuery's `is()` doesn't play well with HTML5 in
							// IE
							return $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time");
						}
					});
			// functions that can be called via $(el).timeago('action')
			// init is default when no action is given
			// functions are called with context of a single element
			var functions = {
				init : function() {
					var refresh_el = $.proxy(refresh, this);
					refresh_el();
					var $s = $t.settings;
					if ($s.refreshMillis > 0) {
						setInterval(refresh_el, $s.refreshMillis);
					}
				},
				update : function(time) {
					$(this).data('timeago', {
								datetime : $t.parse(time)
							});
					refresh.apply(this);
				},
				updateFromDOM : function() {
					$(this).data('timeago', {
						datetime : $t.parse($t.isTime(this) ? $(this)
								.attr("datetime") : $(this).attr("title"))
					});
					refresh.apply(this);
				}
			};
			$.fn.timeago = function(action, options) {
				var fn = action ? functions[action] : functions.init;
				if (!fn) {
					throw new Error("Unknown function name '" + action
							+ "' for timeago");
				}
				// each over objects here and call the requested function
				this.each(function() {
							fn.call(this, options);
						});
				return this;
			};
			function refresh() {
				var data = prepareData(this);
				var $s = $t.settings;
				if (!isNaN(data.datetime)) {
					if ($s.cutoff == 0 || distance(data.datetime) < $s.cutoff) {
						$(this).text(inWords(data.datetime));
					}
				}
				return this;
			}
			function prepareData(element) {
				element = $(element);
				if (!element.data("timeago")) {
					element.data("timeago", {
								datetime : $t.datetime(element)
							});
					var text = $.trim(element.text());
					if ($t.settings.localeTitle) {
						element.attr("title", element.data('timeago').datetime
										.toLocaleString());
					} else if (text.length > 0
							&& !($t.isTime(element) && element.attr("title"))) {
						element.attr("title", text);
					}
				}
				return element.data("timeago");
			}
			function inWords(date) {
				return $t.inWords(distance(date));
			}
			function distance(date) {
				return (new Date().getTime() - date.getTime());
			}
			// fix for IE6 suckage
			document.createElement("abbr");
			document.createElement("time");
		}));